OPERATORS = Set.new([$consts["OR"], $consts["AND"], $consts["BITWISE_OR"], $consts["BITWISE_XOR"],
        $consts["BITWISE_AND"], $consts["EQ"], $consts["NE"], $consts["STRICT_EQ"],
        $consts["STRICT_NE"], $consts["LT"], $consts["LE"], $consts["GE"],
        $consts["GT"], $consts["INSTANCEOF"], $consts["LSH"], $consts["RSH"],
        $consts["URSH"], $consts["PLUS"], $consts["MINUS"], $consts["MUL"],
        $consts["DIV"], $consts["MOD"], $consts["DOT"]])

VALUES = Set.new([$consts["NULL"], $consts["THIS"], $consts["TRUE"], $consts["FALSE"],
        $consts["IDENTIFIER"], $consts["NUMBER"], $consts["STRING"],
        $consts["REGEXP"]])


def get_children (n)
  children = []
  attrs = [n.type, n.value, n.lineno, n.start, n.end, n.tokenizer, n.initializer,
    n.name, n.params, n.funDecls, n.varDecls, n.body, n.functionForm,
    n.assignOp, n.expression, n.condition, n.thenPart, n.elsePart,
    n.readOnly, n.isLoop, n.setup, n.postfix, n.update, n.exception,
    n.object, n.iterator, n.varDecl, n.label, n.target, n.tryBlock,
    n.catchClauses, n.varName, n.guard, n.block, n.discriminant, n.cases,
    n.defaultIndex, n.caseLabel, n.statements, n.statement]
  
  n.length.times do |i|
    children.push(n[i]) if n[i] != n and n[i].class == Node
  end
  
  attrs.length.times do |attr|
    children.push(attrs[attr]) if attrs[attr].class == Node and attrs[attr] != n
  end
  
  return children
end

def resolve_name (n)
  name = ""
  if n.type == $consts["DOT"]
    name = resolve_name(n[0]) + "." + resolve_name(n[1])
  else # INDENTIFIER
    name = n.value
  end
  return name
end
def remove_nils(list)
  new_list = []
  list.each do |line|
    if line != ""
      new_list.push(line)
    end
  end
end

def enumerate_instance_vars(nod)
  
  nodes = get_children(nod)
  nodes.each do |node|
      if node == nil
        next
      else
      print "\nNode Info:  #{$my_const[node.type]} #{node.value}\n"
      instance_vars = node.instance_variables()
      instance_vars.each do |var|
        if var == "@initializer"
          print "Start Initializer Group\n\n"
          initializer_kids = get_children(node.initializer)
          initializer_kids.each do |kid|
            print "\nInitializer Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End Initializer Group\n\n"
        elsif var == "@setup"
          print "Start Setup Group\n\n"
          initializer_kids = get_children(node.setup)
          initializer_kids.each do |kid|
            print "\nSetup Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "Start Setup Group\n\n"
        elsif var == "@expression"
          print "Start Expression Group\n\n"
          initializer_kids = get_children(node.expression)
          initializer_kids.each do |kid|
            print "\nExpression Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End Expression Group\n\n"
        elsif var == "@thenPart"
          print "Start Thenpart Group\n\n"
          initializer_kids = get_children(node.thenPart)
          initializer_kids.each do |kid|
            print "\nThenPart Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End Thenpart Group\n\n"
        elsif var == "@elsePart"
          print "Start elsepart Group\n\n"
          initializer_kids = get_children(node.elsePart)
          initializer_kids.each do |kid|
            print "\nElsepart Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End elsepart Group\n\n"
        elsif var == "@condition"
          print "Start Condition Group\n\n"
          initializer_kids = get_children(node.condition)
          initializer_kids.each do |kid|
            print "\nCondition Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End Condition Group\n\n"
        elsif var == "@update"
          print "Start Update Group\n\n"
          initializer_kids = get_children(node.update)
          initializer_kids.each do |kid|
            print "\nUpdate Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "End Update Group\n\n"
        elsif var == "@body"
          print "Start Body Group\n\n"
          initializer_kids = get_children(node.body)
          initializer_kids.each do |kid|
            print "\nUpdate Node Info:  #{$my_const[kid.type]} #{kid.value}\n"
            enumerate_instance_vars(kid)
          end
          print "Start Body Group\n\n"
        else
          print "#{var} ", eval("node."+var[1..-1]),"\n"
        end
      end
      enumerate_instance_vars(node)
      
    end
  end
end

def get_functions (n, functions = nil)

  functions = {} unless functions

  function = nil
  name = nil

  if n.type == $consts["FUNCTION"] and n.name
    function = n
    name = n.name
  elsif n.type == $consts["ASSIGN"] && n[1].type == $consts["FUNCTION"] && !n[1].name
    function = n[1]
    name = resolve_name(n[0])
  end

  if function
    functions[name] = function
    #puts function.lineno.to_s + ": " + name
  end
  
  children = get_children(n)
  children.length.times do |i|
    get_functions(children[i], functions)
  end

  return functions
end



